package com.jl15988.simpletools.appcore.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jl15988.simpletools.appcore.dto.CategoryDTO;
import com.jl15988.simpletools.appcore.dto.CategoryRequestDTO;
import com.jl15988.simpletools.appcore.entity.AppCategory;
import com.jl15988.simpletools.appcore.entity.Category;
import com.jl15988.simpletools.appcore.mapper.AppCategoryMapper;
import com.jl15988.simpletools.appcore.mapper.CategoryMapper;
import com.jl15988.simpletools.appcore.service.CategoryService;
import com.jl15988.simpletools.appcore.service.FileStorageService;
import com.jl15988.simpletools.common.exception.BusinessException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 分类服务实现类
 *
 * @author jl15988
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private AppCategoryMapper appCategoryMapper;

    @Autowired
    private FileStorageService fileStorageService;

    @Override
    public List<CategoryDTO> getAllCategories() {
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(Category::getSortOrder);
        List<Category> categories = categoryMapper.selectList(wrapper);
        return categories.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    @Override
    public CategoryDTO getCategoryDetail(Long id) {
        Category category = categoryMapper.selectById(id);
        if (category == null) {
            throw new BusinessException("分类不存在");
        }
        return convertToDTO(category);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createCategory(CategoryRequestDTO request, MultipartFile icon) {
        // 检查分类名称是否已存在
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Category::getName, request.getName());
        if (categoryMapper.selectCount(wrapper) > 0) {
            throw new BusinessException("分类名称已存在");
        }

        Category category = new Category();
        BeanUtils.copyProperties(request, category);
        category.setCreatedAt(LocalDateTime.now());

        // 处理图标
        if (icon != null && !icon.isEmpty()) {
            // 先保存分类获取ID
            categoryMapper.insert(category);
            String iconPath = fileStorageService.storeCategoryIcon(icon, category.getId());
            category.setIcon(iconPath);
            categoryMapper.updateById(category);
        } else {
            categoryMapper.insert(category);
        }

        return category.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCategory(CategoryRequestDTO request, MultipartFile icon) {
        Category category = categoryMapper.selectById(request.getId());
        if (category == null) {
            throw new BusinessException("分类不存在");
        }

        // 检查分类名称是否已存在（排除自身）
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Category::getName, request.getName())
                .ne(Category::getId, request.getId());
        if (categoryMapper.selectCount(wrapper) > 0) {
            throw new BusinessException("分类名称已存在");
        }

        BeanUtils.copyProperties(request, category);

        // 处理图标
        if (icon != null && !icon.isEmpty()) {
            // 删除旧图标
            if (category.getIcon() != null && !category.getIcon().isEmpty()) {
                fileStorageService.deleteFile(category.getIcon());
            }
            String iconPath = fileStorageService.storeCategoryIcon(icon, category.getId());
            category.setIcon(iconPath);
        }

        return categoryMapper.updateById(category) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteCategory(Long id) {
        Category category = categoryMapper.selectById(id);
        if (category == null) {
            throw new BusinessException("分类不存在");
        }

        // 检查是否有应用使用该分类
        LambdaQueryWrapper<AppCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppCategory::getCategoryId, id);
        if (appCategoryMapper.selectCount(wrapper) > 0) {
            throw new BusinessException("该分类下有应用，无法删除");
        }

        // 删除图标
        if (category.getIcon() != null && !category.getIcon().isEmpty()) {
            fileStorageService.deleteFile(category.getIcon());
        }

        return categoryMapper.deleteById(id) > 0;
    }

    @Override
    public List<CategoryDTO> getCategoriesByAppId(Long appId) {
        // 查询应用关联的分类ID
        LambdaQueryWrapper<AppCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppCategory::getAppId, appId);
        List<AppCategory> appCategories = appCategoryMapper.selectList(wrapper);
        
        if (appCategories.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 获取分类ID列表
        List<Long> categoryIds = appCategories.stream()
                .map(AppCategory::getCategoryId)
                .collect(Collectors.toList());
        
        // 查询分类信息
        LambdaQueryWrapper<Category> categoryWrapper = new LambdaQueryWrapper<>();
        categoryWrapper.in(Category::getId, categoryIds)
                .orderByAsc(Category::getSortOrder);
        List<Category> categories = categoryMapper.selectList(categoryWrapper);
        
        return categories.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    /**
     * 将实体转换为DTO
     *
     * @param category 分类实体
     * @return 分类DTO
     */
    private CategoryDTO convertToDTO(Category category) {
        CategoryDTO dto = new CategoryDTO();
        BeanUtils.copyProperties(category, dto);
        return dto;
    }
} 